package com.ndp.fb.walle.business.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ndp.ec.core.CatalogService;
import com.ndp.ec.core.FeedService;
import com.ndp.ec.core.ProductSetService;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.productfeed.FeedWeCreatingStatus;
import com.ndp.fb.fbagent.service.ProductCatalogFBService;
import com.ndp.fb.fbagent.service.ProductFeedFBService;
import com.ndp.fb.model.fbagent.param.APIPriority;
import com.ndp.fb.model.fbagent.param.ApiCallBackTarget;
import com.ndp.fb.model.fbagent.param.product.FbFeedParam;
import com.ndp.fb.model.fbagent.param.product.ProductCatalogParam;
import com.ndp.fb.model.fbagent.result.FBSuccess;
import com.ndp.fb.model.fbagent.result.productfeed.FBProductCatalog;
import com.ndp.fb.model.fbagent.result.productfeed.FBProductFeed;
import com.ndp.fb.rdb.api.FbUserRdbService;
import com.ndp.fb.rdb.api.FeedRdbService;
import com.ndp.fb.rdb.api.ProductCatalogRdbService;
import com.ndp.fb.rdb.api.ProductFbFeedRdbService;
import com.ndp.fb.rdb.model.*;
import com.ndp.fb.rdb.model.product.ProductCatalogFbFeed;
import com.ndp.fb.rdb.model.product.ProductCatalogIdAndUserId;
import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.StringUtil;
import com.ndp.fb.walle.business.BusinessManagerService;
import com.ndp.fb.walle.business.ProductCatalogService;
import com.ndp.fb.walle.model.vo.SimpleVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * Created by jacky.cheng on 2016/5/17.
 */
@Component
public class ProductCatalogServiceImpl implements ProductCatalogService {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RedisClient redisClient;

    @Reference
    private ProductCatalogFBService productCatalogFBService;
    @Reference
    private FbUserRdbService fbUserRdbService;
    @Autowired
    private BusinessManagerService businessManagerService;
    @Reference
    private ProductCatalogRdbService productCatalogRdbService;
    @Reference
    private FeedRdbService feedRdbService;
    @Reference
    private ProductFeedFBService productFeedFBService;

    @Reference
    private CatalogService catalogService;
    @Reference
    private FeedService feedService;
    @Reference
    private ProductFbFeedRdbService productFbFeedRdbService;
    @Reference
    private ProductSetService productSetService;
    public List<FBProductCatalog> getFbAll(User user, Long feedId) {
        List<FBProductCatalog> allCatalogFromBM = new ArrayList<>();
        List<BusinessManager> bms = businessManagerService.findByUserId(user.getTicket());
        String token = fbUserRdbService.getTokenByUserId(user.getTicket());
        if(StringUtil.isEmpty(token) || ListUtil.isEmpty(bms))
            return allCatalogFromBM;
        bms.forEach(b -> allCatalogFromBM.addAll(findByBusinessId(token, b.getFbBusinessesId())));
        //过滤掉已经被别的wefeed绑定的
        List<ProductCatalog> all = productCatalogRdbService.findByWeFeedIdNot(feedId, user.getOrgId());
        List<Long> allIds = all.stream().map(ProductCatalog::getFbProductCatalogId).collect(toList());
        return  allCatalogFromBM.stream().filter(i -> !allIds.contains(Long.valueOf(i.getId()))).collect(toList());
    }

    private List<FBProductCatalog> findByBusinessId(String token, Long fbBusinessesId) {
        ProductCatalogParam p = new ProductCatalogParam();
        p.setAccessToken(token);
        p.setBusinessId(fbBusinessesId);
        p.setCallBack(false);
        p.setResultClass(FBProductCatalog.class);
        p.setApiPriorityCode(APIPriority.ProductCatalogCreate.getCode());
        List<FBProductCatalog> bm = productCatalogFBService.getAllCatalogFromBM(p);
        bm.forEach(i-> i.setBusinessId(fbBusinessesId));
        return bm;
    }


    @Override
    public List<ProductCatalog> findByFeed(Long feedId) {
        return productCatalogRdbService.findProductCatalogs(feedId);
    }

    @Override
    public Boolean bind(Long wefeedId, List<SimpleVo> catalogs,String userId) {
        String token = fbUserRdbService.getTokenByUserId(userId);
        List<Long> catalogIds=catalogs.stream().map(i -> Long.valueOf(i.getId())).collect(Collectors.toList());

        List<ProductCatalog> db = productCatalogRdbService.findProductCatalogs(wefeedId);
        //数据库中已经绑定的catalogId
        List<Long> already = db.stream().map(ProductCatalog::getFbProductCatalogId).collect(toList());

        validateCatalog(wefeedId, catalogIds, already, token);

        // 参数中有数据库中没有的，需要insert
        List<SimpleVo> toSave = catalogs.stream()
                .filter(c -> !already.contains(Long.valueOf(c.getId())))
                .collect(toList());

        //数据库中有但是参数中没有的，需要 delete
        List<Long> toDel = already.stream()
                .filter(d -> !catalogIds.contains(d))
                .collect(toList());

        toSave.forEach(i -> {
            Long productCatalogId = Long.valueOf(i.getId());
            ProductWeFeedCatalog temp = new ProductWeFeedCatalog();
            temp.setWeFeedId(wefeedId);
            temp.setFbProductCatalogId(productCatalogId);
            productCatalogRdbService.saveWeFeedCatalog(temp);
            ProductCatalogFbFeed hasCatalog = productCatalogRdbService.findByFbCatalogId(productCatalogId);
            if (hasCatalog == null) {
                ProductCatalog catalog = new ProductCatalog();
                catalog.setFbProductCatalogId(productCatalogId);
                catalog.setProductCatalogName(i.getName());
                catalog.setCreateTime(new Date().getTime());
                productCatalogRdbService.saveCatalog(catalog);
            }
        });

        productCatalogRdbService.deleteByProductCatalogIds(toDel);
        productFbFeedRdbService.deleteByProductCatalogId(toDel);

        //更新wefeed 状态
        if (catalogs.isEmpty()) {
            feedRdbService.updateStatus(wefeedId, FeedWeCreatingStatus.UNBIND_CATALOG.getStatus());
            return true;
        }
        //如果在绑定页面只进行了解绑一些catalog的操作
        if(ListUtil.isEmpty(toSave) && ListUtil.isNotEmpty(toDel)) {
            productSetService.bindProductSet(wefeedId);
            return true;
        }

        if(ListUtil.isEmpty(toSave) && ListUtil.isEmpty(toDel)) {
            logger.info("feed绑定产品目录未增加也未删除");
        } else {
            feedRdbService.updateStatus(wefeedId, FeedWeCreatingStatus.BIND_SUCCESS.getStatus());
            productSetService.bindProductSet(wefeedId);
        }
        return true;
    }


    private void validateCatalog(Long weFeedId, List<Long> catalogIds, List<Long> already, String accessToken) {
        if(ListUtil.isEmpty(catalogIds))
            return;
        for(Long catalogId : catalogIds) {
            //新进来 但是在系统已经绑过得pass
            if(already.contains(catalogId))
                continue;
            //绑定pixel
            catalogService.bindPixel(accessToken, CommonConstants.ViIRTUAL_FB_ID, weFeedId, catalogId,false);
            //删除产品目录下的所有fbfeed 并新建一个
            FbFeedParam fetch = new FbFeedParam();
            fetch.setProductCatalogId(catalogId);
            fetch.setAccessToken(accessToken);
            fetch.setFbAccountId(CommonConstants.ViIRTUAL_FB_ID);

            List<FBProductFeed> fbProductFeeds = productFeedFBService.fetchByCatalogSync(fetch);
            if(ListUtil.isNotEmpty(fbProductFeeds)) {
                for(FBProductFeed fbProductFeed : fbProductFeeds) {
                    feedService.drop(accessToken, Long.valueOf(fbProductFeed.getId()));
                }
            }
            List<Long> ids = new ArrayList<>();
            ids.add(catalogId);
            productFbFeedRdbService.deleteByProductCatalogId(ids);
            redisClient.set("feedgoing_" + weFeedId, 1);
            catalogService.sendFeedToFb(accessToken, weFeedId, catalogId, -1, null);
        }
    }
}
